package com.pz.cloud.framework.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;

public class ExpressionHelper {
	
	private static Logger logger = LoggerFactory.getLogger(ExpressionHelper.class);

	private static StandardEvaluationContext evaluationContext = new StandardEvaluationContext();

	public static StandardEvaluationContext getEvaluationContext() {
		return evaluationContext;
	}
	
	public static void registerFunction(String name, Method method) {
		getEvaluationContext().registerFunction(name, method);
	}
	
	public static void registerFunction(Class<?> clazz) {
		Method[] methods = clazz.getMethods();
		Map<String, Object> map = new HashMap<String, Object>();
		for(Method method : methods) {
			if(method.isAccessible() && Modifier.isStatic(method.getModifiers())) {
				map.put(method.getName(), method);
			}
		}
		getEvaluationContext().setVariables(map);
	}

	public static String parse(String content, Object obj) {
		return parse(content, obj, "#{", "}");
	}

	public static String parse(String content, Object obj, String flagS,
			String flagE) {
		ExpressionParser parser = new SpelExpressionParser();
		Expression expression = parser.parseExpression(content,
				new TemplateParserContext(flagS, flagE));
		try {
			return expression.getValue(getEvaluationContext(), obj, String.class);
		} catch(EvaluationException e) {
			logger.error("EvaluationException", e);
			throw e;
		}
	}

	public static void main(String[] args) {
		Bean bean = new Bean();
		List<String> list = new ArrayList<String>();
		list.add("1");
		list.add("2");
		bean.setList(list);
		Map<String, Object> map = new HashMap<String, Object>();
		Map<String, Object> sub = new HashMap<String, Object>();
		sub.put("aa", "aav");
		map.put("b", sub);
		map.put("a", "av");
		System.out.println(parse("#{[b][aa]}", map));
	}

	static class Bean {
		List<String> list = new ArrayList<String>();
		public void setList(List<String> list) {
			this.list = list;
		}
		public List<String> getList() {
			return list;
		}
	}
}
